import wx
import os
import threading
import subprocess
import math
import custom_events
import ProNOIobjects

class DrawingWindow(wx.Window):
    def __init__ (self, parent, doodle):
        self.doodle = doodle
        super(DrawingWindow, self).__init__(parent, style=wx.NO_FULL_REPAINT_ON_RESIZE)
        
        doodle.Bind(custom_events.EVT_ELLIPSE_DRAW, self.OnEllipseDraw)
        doodle.Bind(wx.EVT_SIZE, self.OnDoodleSize)
        #HACK
        doodle.appx = 1.0
        
        self.btnUndo = wx.Button(self, label='Undo')
        
        self.btnEllipse = wx.ToggleButton(self, label='Ellipse')
        self.btnTube = wx.ToggleButton(self, label='ER Tube')
        self.btnExport = wx.Button(self, label='Export to PDB')
        btnClear = wx.Button(self, label='Clear Objects')
        
        sz = self.doodle.GetClientSize()
        
        self.txtScale = wx.TextCtrl(self, value='1.0')
        
        self.sldAxisA = wx.Slider(self, value=200, minValue=0, maxValue=sz[0], style=wx.SL_HORIZONTAL)
        self.sldAxisB = wx.Slider(self, value=200, minValue=0, maxValue=sz[1], style=wx.SL_HORIZONTAL)
        self.sldPosX = wx.Slider(self, value=200, minValue=0, maxValue=sz[0], style=wx.SL_HORIZONTAL)
        self.sldPosY = wx.Slider(self, value=200, minValue=0, maxValue=sz[1], style=wx.SL_HORIZONTAL)
        self.sldAngle = wx.Slider(self, value=0, minValue=0, maxValue=180, style=wx.SL_HORIZONTAL)
        
        self.txtAxisA = wx.TextCtrl(self, value=str(self.sldAxisA.GetValue()))
        self.txtAxisB = wx.TextCtrl(self, value=str(self.sldAxisB.GetValue()))
        self.txtPosX  = wx.TextCtrl(self, value=str(self.sldPosX.GetValue()))
        self.txtPosY  = wx.TextCtrl(self, value=str(self.sldPosY.GetValue()))
        self.txtAngle = wx.TextCtrl(self, value=str(self.sldAngle.GetValue()))
        
        self.lcEllipses = wx.ListCtrl(self, style=wx.LC_REPORT|wx.LC_NO_HEADER|wx.LC_SINGLE_SEL,size=(100,-1))
        self.lcEllipses.InsertColumn(0, 'Name')
        
        self.btnAdd = wx.Button(self, label='Add')
        self.btnDel = wx.Button(self, label='Delete')
        
        self.Bind(custom_events.EVT_POSTBACK, self.handlePostBack)
        self.Bind(custom_events.EVT_ERROR_POST, self.handleErrorPost)
        
        self.btnUndo.Bind(wx.EVT_BUTTON, self.OnUndoPress)
        
        self.btnEllipse.Bind(wx.EVT_TOGGLEBUTTON, self.toggleEllipse)
        self.btnTube.Bind(wx.EVT_TOGGLEBUTTON, self.toggleTube)
        self.btnExport.Bind(wx.EVT_BUTTON, self.OnExportPress)
        btnClear.Bind(wx.EVT_BUTTON, self.OnClearPress)
        
        self.lcEllipses.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnObjectSelect)
        self.btnAdd.Bind(wx.EVT_BUTTON, self.OnAdd)
        self.btnDel.Bind(wx.EVT_BUTTON, self.OnDel)
        
        self.sldAxisA.Bind(wx.EVT_SCROLL, self.OnAxisAScroll)
        self.sldAxisB.Bind(wx.EVT_SCROLL, self.OnAxisBScroll)
        self.sldPosX.Bind(wx.EVT_SCROLL, self.OnPosXScroll)
        self.sldPosY.Bind(wx.EVT_SCROLL, self.OnPosYScroll)
        self.sldAngle.Bind(wx.EVT_SCROLL, self.OnAngleScroll)
        
        self.txtAxisA.Bind(wx.EVT_TEXT, self.OnAxisATxtChanged)
        self.txtAxisB.Bind(wx.EVT_TEXT, self.OnAxisBTxtChanged)
        self.txtPosX.Bind(wx.EVT_TEXT, self.OnPosXTxtChanged)
        self.txtPosY.Bind(wx.EVT_TEXT, self.OnPosYTxtChanged)
        self.txtAngle.Bind(wx.EVT_TEXT, self.OnAngleTxtChanged)
        
        self.sizer = wx.GridBagSizer()
        ndx = 0
        
        self.sizer.Add(self.txtScale, pos=(ndx,0))
        self.txtScale.Bind(wx.EVT_TEXT, self.OnScaleTxtChanged)
        self.sizer.Add(wx.StaticText(self, label=u'\u212b'+' per pixel'), pos=(ndx,1))
        ndx += 1
        
        #General Properties Box
        self.sboxObject = wx.StaticBox(self, label='Object Properties')
        self.szrObject = wx.StaticBoxSizer(self.sboxObject, orient=wx.VERTICAL)
        
        objndx = 0
        szrObjectInner = wx.GridBagSizer()
        
        szrObjectInner.Add(wx.StaticText(self, label='Precision'), pos=(objndx,0))
        self.txtObjPrecision = wx.TextCtrl(self, value='4')
        self.txtObjPrecision.Bind(wx.EVT_TEXT, self.OnObjPrecisionTxtChanged)
        szrObjectInner.Add(self.txtObjPrecision, pos=(objndx,1))
        objndx += 1
        szrObjectInner.Add(wx.StaticText(self, label='Atomic Charge'), pos=(objndx,0))
        self.txtObjCharge = wx.TextCtrl(self, value=str(4))
        self.txtObjCharge.Bind(wx.EVT_TEXT, self.OnObjChargeTxtChanged)
        szrObjectInner.Add(self.txtObjCharge, pos=(objndx,1))
        objndx += 1
        szrObjectInner.Add(wx.StaticText(self, label='Atomic Radius' + u'\u212b'), pos=(objndx,0))
        self.txtObjRadius = wx.TextCtrl(self, value=str(4)) 
        self.txtObjRadius.Bind(wx.EVT_TEXT, self.OnObjRadiusTxtChanged)
        szrObjectInner.Add(self.txtObjRadius, pos=(objndx,1))
        objndx += 1
        szrObjectInner.Add(wx.StaticText(self, label='Residue'), pos=(objndx,0))
        self.txtObjResidue = wx.TextCtrl(self, value='NIL')
        self.txtObjResidue.Bind(wx.EVT_TEXT, self.OnObjResidueTxtChanged)
        szrObjectInner.Add(self.txtObjResidue, pos=(objndx,1))
        objndx += 1
        szrObjectInner.Add(wx.StaticText(self, label='Atom Type'), pos=(objndx,0))
        self.txtObjAtom = wx.TextCtrl(self, value='OBJ')
        self.txtObjAtom.Bind(wx.EVT_TEXT, self.OnObjAtomTxtChanged)
        szrObjectInner.Add(self.txtObjAtom, pos=(objndx,1))
        objndx += 1
        szrObjectInner.Add(wx.StaticText(self, label='Render Type'), pos=(objndx,0))
        self.rbObjIsSolid = wx.RadioButton(self, label='Solid')
        self.rbObjIsSolid.Bind(wx.EVT_RADIOBUTTON, self.OnObjIsSolidRbChanged)
        szrObjectInner.Add(self.rbObjIsSolid, pos=(objndx,1))
        objndx += 1
        self.rbObjIsSurface = wx.RadioButton(self, label='Surface')
        szrObjectInner.Add(self.rbObjIsSurface, pos=(objndx,1))
        self.rbObjIsSurface.Bind(wx.EVT_RADIOBUTTON, self.OnObjIsSurfaceRbChanged)
        
        self.szrObject.Add(szrObjectInner)
        
        #Ellipsoid Properties Box
        self.sboxEllipsoid = wx.StaticBox(self, label='Ellipsoid Properties')
        self.szrEllipsoid = wx.StaticBoxSizer(self.sboxEllipsoid, orient=wx.VERTICAL)
        
        ellndx = 0
        szrEllipsoidInner = wx.GridBagSizer()
        
        szrEllipsoidInner.Add(self.sldAxisA,pos=(ellndx,0))
        szrEllipsoidInner.Add(self.txtAxisA,pos=(ellndx,1))
        szrEllipsoidInner.Add(wx.StaticText(self, label='X'),pos=(ellndx,2))
        ellndx += 1
        szrEllipsoidInner.Add(self.sldAxisB,pos=(ellndx,0))
        szrEllipsoidInner.Add(self.txtAxisB,pos=(ellndx,1))
        szrEllipsoidInner.Add(wx.StaticText(self, label='Y'),pos=(ellndx,2))
        ellndx += 1
        szrEllipsoidInner.Add(self.sldPosX,pos=(ellndx,0))
        szrEllipsoidInner.Add(self.txtPosX,pos=(ellndx,1))
        szrEllipsoidInner.Add(wx.StaticText(self, label='A'),pos=(ellndx,2))
        ellndx += 1
        szrEllipsoidInner.Add(self.sldPosY,pos=(ellndx,0))
        szrEllipsoidInner.Add(self.txtPosY,pos=(ellndx,1))
        szrEllipsoidInner.Add(wx.StaticText(self, label='B'),pos=(ellndx,2))
        ellndx += 1
        szrEllipsoidInner.Add(self.sldAngle,pos=(ellndx,0))
        szrEllipsoidInner.Add(self.txtAngle,pos=(ellndx,1))
        szrEllipsoidInner.Add(wx.StaticText(self, label=u'\u03f4'),pos=(ellndx,2))
        ellndx += 1

        self.szrEllipsoid.Add(szrEllipsoidInner)
        
        
        #Tube Properties Box
        self.sboxTube = wx.StaticBox(self, label='Tube Properties')
        self.szrTube = wx.StaticBoxSizer(self.sboxTube, orient=wx.VERTICAL)
        
        tbndx = 0
        szrTubeInner = wx.GridBagSizer()
        szrTubeInner.Add(wx.StaticText(self, label='Tube Width'), pos=(tbndx,0))
        self.txtTubeWidth = wx.TextCtrl(self, value='3')
        self.txtTubeWidth.Bind(wx.EVT_TEXT, self.OnTubeWidthTxtChanged)
        szrTubeInner.Add(self.txtTubeWidth, pos=(tbndx,1))
        tbndx += 1
        szrTubeInner.Add(wx.StaticText(self, label='Bias'), pos=(tbndx,0))
        self.txtTubeBias = wx.TextCtrl(self, value='0')
        self.txtTubeBias.Bind(wx.EVT_TEXT, self.OnTubeBiasTxtChanged)
        szrTubeInner.Add(self.txtTubeBias, pos=(tbndx,1))
        tbndx += 1
        szrTubeInner.Add(wx.StaticText(self, label='Tension'), pos=(tbndx,0))
        self.txtTubeTension = wx.TextCtrl(self, value='0')
        self.txtTubeTension.Bind(wx.EVT_TEXT, self.OnTubeTensionTxtChanged)
        szrTubeInner.Add(self.txtTubeTension, pos=(tbndx,1))
        
        self.szrTube.Add(szrTubeInner)
        
        self.sizer.Add(self.btnEllipse,pos=(ndx,0))
        self.sizer.Add(self.btnTube,pos=(ndx,1))
        ndx += 1
        self.sizer.Add(wx.StaticText(self),pos=(ndx,0))
        self.sizer.Add(wx.StaticText(self),pos=(ndx,1))
        ndx += 1
        self.sizer.Add(self.btnExport,pos=(ndx,0))
        self.sizer.Add(btnClear,pos=(ndx,1))
        ndx += 1
        self.sizer.Add(self.lcEllipses,pos=(ndx,0),span=(3,1))
        self.sizer.Add(self.btnAdd,pos=(ndx,1))
        ndx += 1
        self.sizer.Add(self.btnDel,pos=(ndx,1))
        ndx += 1
        self.sizer.Add(self.btnUndo, pos=(ndx,1))
        ndx += 1
        self.sizer.Add(self.szrObject,pos=(ndx,0), span=(1,2))
        ndx += 1
        self.sizer.Add(self.szrEllipsoid,pos=(ndx,0), span=(1,2))
        ndx += 1
        self.sizer.Add(self.szrTube,pos=(ndx,0), span=(1,2))
        ndx += 1
        self.SetSizer(self.sizer)
        self.sizer.Hide(self.szrObject)
        #TODO accidentally hides the labels for the sliders, might need to call parent's sizer.Layout() on show()
        self.sizer.Hide(self.szrEllipsoid)
        self.sizer.Hide(self.szrTube)
        
    def OnScaleTxtChanged (self, evt):
        try:
            self.doodle.appx = float(self.txtScale.GetValue())
        except ValueError:
            pass
        self.doodle.RedrawEllipse()
    def OnUndoPress (self, evt):
        if (self.doodle.activeObject != -1):
            obj = self.doodle.ellipses[self.doodle.activeObject]
            if (obj.objtype == 1):
                obj.ctrlpts.pop()
                obj.points.pop()
            self.doodle.RedrawEllipse()
            
    #General Object Property changes
    def OnObjPrecisionTxtChanged (self, evt):
        try:
            self.doodle.ellipses[self.doodle.activeObject].precision = float(evt.GetString())
        #ignore error for now, just dont set it    
        except ValueError:
            pass
    def OnObjChargeTxtChanged (self, evt):
        try:
            self.doodle.ellipses[self.doodle.activeObject].charge = float(evt.GetString())
        except ValueError:
            pass
    def OnObjRadiusTxtChanged (self, evt):
        try:
            self.doodle.ellipses[self.doodle.activeObject].radius = float(evt.GetString())
        except ValueError:
            pass
    def OnObjResidueTxtChanged (self, evt):
        self.doodle.ellipses[self.doodle.activeObject].residue = evt.GetString()
    def OnObjAtomTxtChanged (self, evt):
        self.doodle.ellipses[self.doodle.activeObject].atom = evt.GetString()
    def OnObjIsSolidRbChanged (self, evt):
        self.doodle.ellipses[self.doodle.activeObject].fill = ProNOIobjects.object.solid
    def OnObjIsSurfaceRbChanged (self, evt):
        self.doodle.ellipses[self.doodle.activeObject].fill = ProNOIobjects.object.surface
        
    #Tube Property Change Events
    def OnTubeWidthTxtChanged (self, evt):
        try:
            self.doodle.ellipses[self.doodle.activeObject].width = float(evt.GetString())
        except ValueError:
            pass
        self.doodle.RedrawEllipse()
    def OnTubeTensionTxtChanged (self, evt):
        try:
            self.doodle.ellipses[self.doodle.activeObject].tension = float(evt.GetString())
            #TODO redraw tube with new tension value
        except ValueError:
            pass
        self.doodle.RedrawEllipse()
    def OnTubeBiasTxtChanged (self, evt):
        try:
            self.doodle.ellipses[self.doodle.activeObject].bias = float(evt.GetString())
            #TODO redraw tube with new bias value
        except ValueError:
            pass
        self.doodle.RedrawEllipse()
    
    #Ellipsoid Property Change Events        
    def OnAxisAScroll (self, evt):
        self.txtAxisA.ChangeValue(str(evt.GetEventObject().GetValue()))
        self.callRedraw()
    def OnAxisBScroll (self, evt):
        self.txtAxisB.ChangeValue(str(evt.GetEventObject().GetValue()))
        self.callRedraw()
    def OnPosXScroll (self, evt):
        self.txtPosX.ChangeValue(str(evt.GetEventObject().GetValue()))
        self.callRedraw()
    def OnPosYScroll (self, evt):
        self.txtPosY.ChangeValue(str(evt.GetEventObject().GetValue()))
        self.callRedraw()
    def OnAngleScroll (self, evt):
        self.txtAngle.ChangeValue(str(evt.GetEventObject().GetValue()))
        self.callRedraw()
    
    def OnAxisATxtChanged(self, evt):
        self.sldAxisA.SetValue(float(evt.GetString()))
        self.callRedraw()
    def OnAxisBTxtChanged(self, evt):    
        self.sldAxisB.SetValue(float(evt.GetString()))
        self.callRedraw()
    def OnPosXTxtChanged (self, evt):
        self.sldPosX.SetValue(float(evt.GetString()))
        self.callRedraw()
    def OnPosYTxtChanged (self, evt):
        self.sldPosY.SetValue(float(evt.GetString()))
        self.callRedraw()
    def OnAngleTxtChanged(self, evt):    
        self.sldAngle.SetValue(float(evt.GetString()))
        self.callRedraw()
        
    #Shows or hides the groupboxes based on the current type of object selected    
    def toggleEllipseControls(self,objtype):
        self.sizer.Show(self.szrObject)
        if (objtype == 0):
            self.sizer.Show(self.szrEllipsoid)
            self.sizer.Hide(self.szrTube)
        elif(objtype == 1):
            self.sizer.Hide(self.szrEllipsoid)
            self.sizer.Show(self.szrTube)
        elif(objtype == -1):
            self.sizer.Hide(self.szrEllipsoid)
            self.sizer.Hide(self.szrTube)
            self.sizer.Hide(self.szrObject)
        self.sizer.Layout()
            
    def OnExportPress (self,evt):
        try:
            appx = float(self.txtScale.GetValue())
            scale = self.doodle.sizeScale
            if (len(self.doodle.ellipses) == 0):
                return
            self.btnExport.Disable()
            self.completedRuns = 0
            self.numRuns = len(self.doodle.ellipses)
            self.runsFailed = False
            i = 0
            if os.access('bigfile.pqr', os.F_OK):
                os.remove('bigfile.pqr')
            for ell in self.doodle.ellipses:
                cmdstr = ''
                fname = ''
                if (ell.objtype == 0):
                    fname = 'ellipse'+str(i)+'.pqr'
                    if os.access(fname, os.F_OK):
                        os.remove(fname)
                    x = ell.x * appx * scale[0]
                    y = ell.y * appx * scale[1]
                    a = ell.a * appx * scale[0]
                    b = ell.b * appx * scale[1]
                    t = ell.theta
                    
                    axes = (a/2.0, b/2.0)
                    origin = (x,y)#(x+axes[0]/2.0, y+axes[1]/2.0)
                    args = 'e'+str(origin[0]) +','+ str(origin[1])+',0,'+ str(axes[0]) +','+ str(axes[1]) +','+ str(t)
                elif (ell.objtype == 1):
                    fname = 'tube'+str(i)+'.pqr'
                    dname = 'tube'+str(i)+'.dat'
                    if os.access(fname, os.F_OK):
                        os.remove(fname)
                    if os.access(dname, os.F_OK):
                        os.remove(dname)
                    #print ell
                    fhandle = open(dname, 'w')
                    for pt in ell.ctrlpts:
                        (x,y) = (pt[0] * appx * scale[0], pt[1] * appx * scale[1])
                        fhandle.write(str(x) + ' ' + str(y) + '\n')
                    fhandle.close()
                    args = 't'+str(ell.width)+','+str(ell.bias)+','+ str(ell.tension) +','+dname
                
                cmdstr = r'"shape.exe" -pqr -atom='+ ell.atom + ' -q=' + str(ell.charge) + ' -r=' + str(ell.radius) + ell.GetFillStr() + ' -p='+str(ell.precision)+' -short='+args+' -o='+fname
                    
                print cmdstr
                ellipsePID = subprocess.Popen(cmdstr)
                #HACK commented out the kill timer, shape could hang if it doesnt work out...
                ellipseTimer = threading.Timer(30.0, self.killProcess, args=[ellipsePID])
                ellipseTimer.start()
                ellipseThread = threading.Thread(target=self.manageProcess, args=[ellipsePID])
                ellipseThread.start()
                i += 1
        except ValueError:
            print 'Angstroms per pixel value was not a float, export failed.'

    def manageProcess (self, pid):
        pid.wait()
        print pid.returncode
        evt = custom_events.ProcessPostBackEvent(calltype=0,success=pid.returncode)
        wx.PostEvent(self, evt)
        
    '''Handle the callback from the C++ process and post results'''    
    def handlePostBack (self, evt):
        #check if process exited correctly, might raise a dialog box...
        self.completedRuns += 1
        if evt.success != 0:
            self.runsFailed = True
        #wait til all of the runs have completed...
        if (self.numRuns == self.completedRuns):
            self.handleResults()
    def handleResults(self):
        print 'Handling!'
        if (self.runsFailed is not True):
            bigfile = open("bigfile.pqr", "w")
            i = 0
            for ell in self.doodle.ellipses:
                fname = str(i)+".pqr"
                if (ell.objtype == 0):
                    fname = 'ellipse'+fname
                elif(ell.objtype == 1):    
                    fname = 'tube'+fname
                ellfile = open(fname,  "r")
                bigfile.write(ellfile.read())
                ellfile.close()
                i += 1
            bigfile.close()
            #TODO open Chimera or some other appropriate program...
        self.btnExport.Enable()
        
    '''Kill the process if the timeout limit is reached and the process has not exited cleanly yet 
    (a threading.Timer class calls this)'''
    def killProcess (self, pid):
        if (pid.poll() is None):
            print "terminating shape.exe process"
            pid.terminate()
            self.completedRuns += 1
            self.runsFailed = True
            if (self.numRuns == self.completedRuns):
                self.handleResults()
    
    def OnClearPress (self, evt):
        self.doodle.ellipses = list()
        self.lcEllipses.DeleteAllItems()
        self.toggleEllipseControls(-1)
        self.doodle.reInitBuffer = True
        
    def OnObjectSelect (self, evt):
        ndx = self.lcEllipses.GetFirstSelected()
        self.doodle.activeObject = ndx
        obj = self.doodle.ellipses[ndx]
        self.doodle.drawTool = self.doodle.ellipses[ndx].objtype
        
        if (self.doodle.ellipses[ndx].objtype == 0):
            self.btnTube.SetValue(False)
            self.btnEllipse.SetValue(True)
            item = self.lcEllipses.GetFirstSelected()
            self.lcEllipses.SetItemText(item, 'ellipse'+str(ndx))
            self.UpdateEllipseProperties(obj)
        elif (self.doodle.ellipses[ndx].objtype == 1):
            self.btnEllipse.SetValue(False)
            self.btnTube.SetValue(True)
            item = self.lcEllipses.GetFirstSelected()
            self.lcEllipses.SetItemText(item, 'tube'+str(ndx))
            self.UpdateTubeProperties(obj)
        self.toggleEllipseControls(self.doodle.drawTool)
        self.UpdateObjectProperties(obj)
            
            
        self.doodle.RedrawEllipse()
        
    def toggleEllipse (self, evt):
        self.doodle.drawTool = 0
        self.btnTube.SetValue(False)
        self.btnEllipse.SetValue(True)
        item = self.lcEllipses.GetFirstSelected()
        if (item != -1):
            ndx = self.doodle.activeObject
            self.lcEllipses.SetItemText(item, 'ellipse'+str(ndx))
            self.doodle.ellipses[ndx] = ProNOIobjects.object.initEllipsoid(0,0,0.1,0.1,0)
        self.callRedraw()
        self.toggleEllipseControls(self.doodle.drawTool)
    def toggleTube (self, evt):
        self.doodle.drawTool = 1
        self.btnEllipse.SetValue(False)
        self.btnTube.SetValue(True)
        item = self.lcEllipses.GetFirstSelected()
        if (item != -1):
            ndx = self.doodle.activeObject
            self.lcEllipses.SetItemText(item, 'tube'+str(ndx))
            self.doodle.ellipses[ndx] = ProNOIobjects.object.initTube(1.0,0,0)
        
        self.callRedraw()
        self.toggleEllipseControls(self.doodle.drawTool)
        
    def UpdateEllipseProperties (self, obj):
        x = obj.x * self.doodle.sizeScale[0]
        y = obj.y * self.doodle.sizeScale[1]
        a = obj.a * self.doodle.sizeScale[0]
        b = obj.b * self.doodle.sizeScale[1]
        t = obj.theta
        self.sldAxisA.SetValue(a)
        self.txtAxisA.ChangeValue(str(a))
        self.sldAxisB.SetValue(b)
        self.txtAxisB.ChangeValue(str(b))
        self.sldPosX.SetValue(x)
        self.txtPosX.ChangeValue(str(x))
        self.sldPosY.SetValue(y)
        self.txtPosY.ChangeValue(str(y))
        self.sldAngle.SetValue(math.degrees(t))
        self.txtAngle.ChangeValue(str(math.degrees(t)))
            
    def UpdateTubeProperties (self, obj):
        self.txtTubeWidth.ChangeValue(str(obj.width))
        self.txtTubeBias.ChangeValue(str(obj.bias))
        self.txtTubeTension.ChangeValue(str(obj.tension))
    def UpdateObjectProperties (self, obj):
        self.txtObjPrecision.ChangeValue(str(obj.precision))
        self.txtObjAtom.ChangeValue(obj.atom)
        self.txtObjResidue.ChangeValue(obj.residue)
        self.txtObjRadius.ChangeValue(str(obj.radius))
        self.txtObjCharge.ChangeValue(str(obj.charge))
        #might not need to set both...
        self.rbObjIsSolid.SetValue(obj.IsSolid())
        self.rbObjIsSurface.SetValue(not (obj.IsSolid()))

    def OnAdd (self, evt):
        cnt = self.lcEllipses.GetItemCount()
        if (self.doodle.drawTool == 0):
            self.lcEllipses.Append(['ellipse'+str(cnt)])
            self.doodle.ellipses.append(ProNOIobjects.object.initEllipsoid(0,0,0.1,0.1,0))
        elif (self.doodle.drawTool == 1):
            self.lcEllipses.Append(['tube'+str(cnt)])
            self.doodle.ellipses.append(ProNOIobjects.object.initTube(1.0,0,0))
        self.lcEllipses.Select(cnt)
    
    def OnDel (self, evt):
        ndx = self.lcEllipses.GetFirstSelected()
        if (ndx > -1):
            #TODO it should always be the active ellipse tho...
            if (ndx == self.doodle.activeObject):
                self.doodle.activeObject = -1
            self.lcEllipses.DeleteItem(ndx)
            del self.doodle.ellipses[ndx]
            cnt = self.lcEllipses.GetItemCount()
            self.lcEllipses.Select(cnt-1)
            self.callRedraw()
            if (self.lcEllipses.GetFirstSelected() == -1):
                self.toggleEllipseControls(-1)
    
    def callRedraw (self):
        if (len(self.doodle.ellipses) > 0):
            if (self.doodle.drawTool == 0):
                x = self.sldPosX.GetValue() / self.doodle.sizeScale[0]
                y = self.sldPosY.GetValue() / self.doodle.sizeScale[1]
                a = self.sldAxisA.GetValue() / self.doodle.sizeScale[0]
                b = self.sldAxisB.GetValue() / self.doodle.sizeScale[1]
                t = math.radians(self.sldAngle.GetValue())
                self.doodle.ellipses[self.doodle.activeObject] = ProNOIobjects.object.initEllipsoid(x, y, a, b, t)
        self.doodle.RedrawEllipse()
    def OnEllipseDraw (self, evt):
        x = evt.ellipse.x * self.doodle.sizeScale[0]
        y = evt.ellipse.y * self.doodle.sizeScale[1]
        a = evt.ellipse.a * self.doodle.sizeScale[0]
        b = evt.ellipse.b * self.doodle.sizeScale[1]
        t = evt.ellipse.theta
        self.sldAxisA.SetValue(a)
        self.txtAxisA.ChangeValue(str(a))
        self.sldAxisB.SetValue(b)
        self.txtAxisB.ChangeValue(str(b))
        self.sldPosX.SetValue(x)
        self.txtPosX.ChangeValue(str(x))
        self.sldPosY.SetValue(y)
        self.txtPosY.ChangeValue(str(y))
        self.sldAngle.SetValue(t)
        self.txtAngle.ChangeValue(str(t))
        
    def OnDoodleSize (self, evt):
        nsz = evt.GetSize()
        
        self.sldPosX.SetMax(nsz[0])
        self.sldPosY.SetMax(nsz[1])
        self.sldAxisA.SetMax(nsz[0])
        self.sldAxisB.SetMax(nsz[1])
        
        if (self.doodle.activeObject != -1):
            obj = self.doodle.ellipses[self.doodle.activeObject]
            if (obj.objtype == 0):
                nx = obj.x * nsz[0]
                ny = obj.y * nsz[1]
                na = obj.a * nsz[0]
                nb = obj.b * nsz[1]
                self.sldPosX.SetValue(nx)
                self.sldPosY.SetValue(ny)
                self.sldAxisA.SetValue(na)
                self.sldAxisB.SetValue(nb)
        
        self.doodle.RedrawEllipse()
        
    def handleErrorPost(self, evt):
        print evt.msg
